package com.oss.robot.link;

import java.util.ArrayList;
import java.util.List;

import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.Tag;
import org.htmlparser.filters.HasAttributeFilter;
import org.htmlparser.filters.LinkStringFilter;
import org.htmlparser.tags.Div;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
import org.htmlparser.visitors.NodeVisitor;

import com.oss.model.Constants;
import com.oss.model.Link;
import com.oss.model.Task;
import com.oss.robot.AbstractRetrieveRobot;

/**
 * 解析首页得到链接任务，二次解析链接得到Link
 * 
 * @TODO 进行DZone多个模板的链接任务提取
 * 
 * @author xueqiang.mi
 * @since 2010-7-16
 */
public class DZoneRobot extends AbstractRetrieveRobot {
  class DZoneRobotVisitor extends NodeVisitor {
    private Link lnk;

    public DZoneRobotVisitor(Link lnk) {
      this.lnk = lnk;
    }

    public void visitTag(Tag tag) {
      String clazz = tag.getAttribute("class");
      if (clazz == null) {
        return;
      }
      if (clazz.equals("ldTitle")) {
        Node childTag = tag.getFirstChild();
        if (childTag instanceof LinkTag) {
          LinkTag linkTag = (LinkTag) childTag;
          lnk.setName(linkTag.getLinkText());
          lnk.setUrl(linkTag.getLink());
        }
      }
      if (clazz.equals("ldBlurbText")) {
        String desc = tag.getFirstChild().getText();
        lnk.setDescription(desc);
      }
      if (clazz.equals("ldUser")) {
        NodeList nodeList = tag.getChildren().extractAllNodesThatMatch(new LinkStringFilter(""), true);
        if (nodeList.size() > 2) {
          lnk.setAuthor(nodeList.elementAt(1).getFirstChild().getText());
          lnk.setBlog(nodeList.elementAt(2).getFirstChild().getText());
        }
      }
    }
  }

  static public final String URL = "http://dzone.com";
  static public final String SOURCE = "DZone.COM";
  static public final Integer TASK_NUMBER_PER_TIME = 15;

  @Override
  @SuppressWarnings("serial")
  public void extractData(Task task) throws ParserException {
    String link = task.getLink();
    Parser parser = new Parser(link);
    NodeList nodeList = parser.extractAllNodesThatMatch(new HasAttributeFilter("id", "linkDetails"));
    nodeList = nodeList.extractAllNodesThatMatch(new NodeFilter() {
      @Override
      public boolean accept(Node node) {
        if (node instanceof Div) {
          return true;
        }
        return false;
      }
    }, true);

    Link lnk = new Link();
    lnk.setSource(SOURCE);
    DZoneRobotVisitor visitor = new DZoneRobotVisitor(lnk);
    for (Node node : nodeList.toNodeArray()) {
      node.accept(visitor);
    }
    lnkService.add(lnk);
  }

  @Override
  public String getSource() {
    return SOURCE;
  }

  @Override
  public Integer getTasksNumber() {
    return TASK_NUMBER_PER_TIME;
  }

  @Override
  @SuppressWarnings("serial")
  public List<Task> retrieveLinks() throws Exception {
    Parser parser = new Parser(URL);
    NodeList nodeList = parser.extractAllNodesThatMatch(new NodeFilter() {
      public boolean accept(Node node) {
        if (node instanceof LinkTag) {
          Tag link = (Tag) node;
          if (link.getFirstChild() == null) {
            return false;
          }
          if (link.getFirstChild().getText().startsWith("more")) {
            return true;
          }
        }
        return false;
      }
    });
    List<Task> tasks = new ArrayList<Task>();
    for (Node node : nodeList.toNodeArray()) {
      LinkTag link = (LinkTag) node;
      Task task = new Task(link.getLink(), SOURCE, Constants.ENTRY_LINK);
      tasks.add(task);
    }
    return tasks;
  }
}
